package com.wty.example.publish;


//对象发布指的是外部可以调用该对象
//对象逸出指的是对象未构建完成便被发布了


//安全发布对象的几种情况
//1.静态初始化函数中初始化一个对象的引用
//2.将对象的引用放在一个被锁保护的域中
//3.将对象的引用保存在voliate或者atomicReference中
//4.将对象的引用保存到某个正确构造对象的final类型域中


import com.wty.annotations.ThreadSafe;

//单例模式 懒汉式 双重同步锁
@ThreadSafe
public class publishDemo3 {

    private publishDemo3() {

    }

    private static volatile  publishDemo3 instance = null;

    //如果锁一个方法的话 会造成效率很低下
    /*public synchronized publishDemo3 getInstance() {
        if (instance == null) {
            instance = new publishDemo3();
        }
        return instance;
    }*/




    //但是这也不是线程安全的 为什么呢
    //因为java内存有重排序

//    1.分配对象的内存空间
//    2.初始化对象
//    3.对象指向内存空间

//    1.分配对象内存空间
//    2.对象指向内存空间
//    3.初始化对象
// 这种情况的话 一个线程创建了对象 但是对象并没有初始化 另一个线程以为已经有了对象 然后调用 结果却是空

//    解决方法 instance加volatile关键字


    public static publishDemo3 getInstance() {
        if (instance == null) {
            synchronized (publishDemo3.class) {
                //肯定是只有一个线程能执行这段代码
                if (instance == null) {
                    instance = new publishDemo3();
                }
            }
        }
        return instance;
    }

}
